﻿using Abp;
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.Domain.Repositories;
using Abp.Extensions;
using Abp.Linq.Extensions;
using Microsoft.EntityFrameworkCore;
using Mt.Site.Application.Dto;
using Mt.Site.Application.Modules.Dto;
using Mt.Site.Core.Navigations.Entities;
using Mt.Site.Core.Navigations.Modules;
using Mt.Site.Core.Navigations.Permissions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace Mt.Site.Application.Modules
{
    [AbpAuthorize(MenuPermissions.Pages_Administration_FrontendPage)]
    public class FrontendPageAppService : MtSiteAppServiceBase, IFrontendPageAppService
    {
        private readonly IFrontendPageManager _frontEndPageManager;
        private readonly IModuleManager _moduleManager;
        private readonly IRepository<FrontEndPage, Guid> _frontEndPageRepository;

        public FrontendPageAppService(
            IModuleManager moduleManager,
            IFrontendPageManager frontEndPageManager,
            IRepository<FrontEndPage, Guid> frontEndPageRepository)
        {
            _moduleManager = moduleManager;
            _frontEndPageManager = frontEndPageManager;
            _frontEndPageRepository = frontEndPageRepository; 
        }

        [AbpAuthorize(MenuPermissions.Pages_Administration_FrontendPage_Create)]
        public async Task CreateAsync(CreateFrontendPageDto input)
        {
            var m = ObjectMapper.Map<FrontEndPage>(input);
            m.Order = await _frontEndPageManager.GetMaxOrder();
            await _frontEndPageManager.CreateAsync(m);
        }


        [AbpAuthorize(MenuPermissions.Pages_Administration_FrontendPage_Edit)]
        public async Task UpdateAsync(UpdateFrontendPageDto input)
        {
            var m = await _frontEndPageManager.GetAsync(input.Id);
            AppCheck.CheckLastModificationTime(input.LastModificationTime, m, L("DataHasBeenChanged"));

            m.IsActive = input.IsActive;
            m.Name = input.Name;
            m.Description = input.Description;
            m.BackEndModuleId = input.BackEndModuleId;
            m.Url = input.Url;
            m.Target = input.Target;
            m.ControllerName = input.ControllerName;
            m.ActionName = input.ActionName;

            m.Order = input.Order;

            m.IsDetailPage = input.IsDetailPage;
            m.IsDefault = input.IsDefault;
            m.DetailPageId = input.DetailPageId;

            await _frontEndPageManager.UpdateAsync(m);
        }

        [AbpAuthorize(MenuPermissions.Pages_Administration_FrontendPage_Delete)]
        public async Task DeleteAsync(EntityDto<Guid> input)
        {
            await _frontEndPageManager.DeleteAsync(input.Id);
        }

        [AbpAuthorize(MenuPermissions.Pages_Administration_FrontendPage_Delete)]
        public async Task DeleteListAsync(List<Guid> input)
        {
            await _frontEndPageManager.DeleteListAsync(input);
        }

        public async Task<List<NameValue>> GetDetailPagesAsync(EntityDto<Guid> input)
        {
            if(input.Id == Guid.Empty)
            {
                return new List<NameValue>();
            }

            return await _frontEndPageManager.GetDetailPagesAsync(input.Id);
        }

        public async Task CopyNewOneAsync(EntityDto<Guid> input)
        {
            await _frontEndPageManager.CopyNewPage(input.Id);
        }

        public async Task<GetFrontendPageForEditOutput> GetForEditAsync(GetFrontendPageForEditInput input)
        {
            var dto = new GetFrontendPageForEditOutput();

            if (input.FrontendPageId.HasValue)
            {
                var frontEndPage = await _frontEndPageManager.GetAsync(input.FrontendPageId.Value);
                dto.FrontendPage = ObjectMapper.Map<FrontendPageDto>(frontEndPage);

                if(frontEndPage.BackEndModuleId != Guid.Empty)
                {
                    dto.DetailPages = await _frontEndPageManager.GetDetailPagesAsync(frontEndPage.BackEndModuleId);
                }
            }

            if (input.BackEndModuleId.HasValue && dto.DetailPages == null)
            {
                dto.DetailPages = await _frontEndPageManager.GetDetailPagesAsync(input.BackEndModuleId.Value);
            }
            return dto;
        }

        public async Task<PagedResultDto<PagedFrontendPageDto>> GetPagedFrontendPages(PagedFrontendPageInput input)
        {
            var query = _frontEndPageRepository.GetAll()
                .WhereIf(input.BackEndModuleId != null, t => t.BackEndModuleId == input.BackEndModuleId)
                .WhereIf(input.PageType == PageType.Menu, t=>t.IsDetailPage == false)
                .WhereIf(input.PageType == PageType.Detail, t => t.IsDetailPage == true)
                .WhereIf(!input.Filter.IsNullOrEmpty(), t => t.Name.Contains(input.Filter));

            query = !input.Sorting.IsNullOrEmpty() ? query.OrderBy(input.Sorting) : query.OrderByDescending(t => t.Order).ThenByDescending(t => t.CreationTime);

            var count = query.Count();
            var list = await query.PageBy(input).ToListAsync();
            return new PagedResultDto<PagedFrontendPageDto>(count, ObjectMapper.Map<List<PagedFrontendPageDto>>(list));
        }

        [AbpAuthorize(MenuPermissions.Pages_Administration_FrontendPage_Edit)]
        public async Task SetStatus(SetStatusInput input)
        {
            await _frontEndPageManager.SetStatus(input.IdList, input.IsActive);
        }

        [AbpAuthorize(MenuPermissions.Pages_Administration_FrontendPage_Edit)]
        public async Task SwapSortNumber(SwapSortNumberInput input)
        {
            var idList = input.IdOrderList.Select(c => c.Id).ToList();
            var orderList = input.IdOrderList.Select(c => c.Order).ToList();

            var list = await _frontEndPageRepository.GetAllListAsync(c => idList.Contains(c.Id));

            foreach (var item in list)
            {
                var index = idList.FindIndex(c => c == item.Id);
                if (index != -1)
                {
                    item.Order = orderList[index];
                }
            }
        }

        [AbpAuthorize(MenuPermissions.Pages_Administration_FrontendPage_Edit)]
        public async Task SetNewSorNumber(NewSortNumberInput input)
        {
            var ob = await _frontEndPageRepository.GetAsync(input.Id);
            ob.Order = input.NewNumber;
            await _frontEndPageRepository.UpdateAsync(ob);
        }

        public async Task<List<NameValue>> GetAllModuleDataAsync()
        {
            var list = (await _moduleManager.GetBackEndModuleList())
                .Select(c => new NameValue(c.DisplayName, c.Id.ToString()))
                .ToList();

            list.Insert(0, new NameValue(L("UnSelect"), ""));

            return list;
        }
    }
}
